package com.ysc.task.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ysc.task.constant.YSConstant;
import com.ysc.task.entity.User;
import com.ysc.task.entity.dto.UserLoginDTO;
import com.ysc.task.entity.dto.UserRegisterDTO;
import com.ysc.task.entity.dto.UserUpdateDTO;
import com.ysc.task.entity.vo.UserLoginVO;
import com.ysc.task.exception.YscException;
import com.ysc.task.mapper.UserMapper;
import com.ysc.task.service.IUserService;
import com.ysc.task.util.JwtTool;
import com.ysc.task.util.R;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

/**
 * Version: 1.0
 * Class Name: UserServiceImpl
 * Description: TODO(一句话描述功能)
 * Author: ysc
 * Date: 2024/3/31 13:19
 */
@Service
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    private final UserMapper userMapper;

    @Override
    public R login(UserLoginDTO userLoginDTO) {
        String username = userLoginDTO.getUsername();
        String password = userLoginDTO.getPassword();
        if ( !StringUtils.hasText(username) ) {
            throw new YscException(YSConstant.USERNAME_MUST_HAVE);
        }
        if ( !StringUtils.hasText(password) ) {
            throw new YscException(YSConstant.PASSWORD_MUST_HAVE);
        }
        User loginUser = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getUsername, username));
        if ( ObjectUtils.isEmpty(loginUser) ) {
            throw new YscException(YSConstant.USERNAME_NOT_FOUND);
        }
        boolean matches = new BCryptPasswordEncoder().matches(password, loginUser.getPassword());
        if ( !matches ) {
            throw new YscException(YSConstant.PASSWORD_ERROR);
        }
        String token = JwtTool.createJWT(loginUser.getUserId().toString());
        UserLoginVO userVO = new UserLoginVO();
        BeanUtils.copyProperties(loginUser, userVO, UserLoginVO.class);
        userVO.setToken(token);
        return R.ok().data("user", userVO);
    }

    @Override
    public R register(UserRegisterDTO userRegisterDTO) {
        String username = userRegisterDTO.getUsername();
        String password = userRegisterDTO.getPassword();
        String confirmPassword = userRegisterDTO.getConfirmPassword();

        if ( !StringUtils.hasText(username) ) {
            throw new YscException(YSConstant.USERNAME_MUST_HAVE);
        }
        if ( !StringUtils.hasText(password) ) {
            throw new YscException(YSConstant.PASSWORD_MUST_HAVE);
        }
        if ( !StringUtils.hasText(confirmPassword) ) {
            throw new YscException(YSConstant.CONFIRM_PASSWORD_MUST_HAVE);
        }
        if ( !confirmPassword.equals(password) ) {
            throw new YscException(YSConstant.PASSWORD_NOT_EQUAL);
        }
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
        lqw.eq(User::getUsername, username);
        User conflict = userMapper.selectOne(lqw);
        if ( !ObjectUtils.isEmpty(conflict) ) {
            throw new YscException(YSConstant.USERNAME_IS_EXIST);
        }
        if ( username.length() < 6 ) {
            throw new YscException(YSConstant.USERNAME_TO_SHORT);
        }
        if ( username.length() > 16 ) {
            throw new YscException(YSConstant.USERNAME_TO_LONG);
        }
        if ( password.length() < 6 ) {
            throw new YscException(YSConstant.PASSWORD_TO_SHORT);
        }
        User user = new User();
        BeanUtils.copyProperties(userRegisterDTO, user, User.class);
        user.setPassword(new BCryptPasswordEncoder().encode(password));
        int i = userMapper.insert(user);
        if ( i < 1 ) {
            throw new YscException(YSConstant.NETWORK_ERROR);
        }
        return R.ok();
    }

    @Override
    public R update(UserUpdateDTO userUpdateDTO) {
        User user = new User();
        user.setUserId(userUpdateDTO.getUserId());
        user.setEmail(userUpdateDTO.getEmail());
        userMapper.updateById(user);
        return R.ok();
    }
}
